package com.accessibleworlds.util;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.spec.KeySpec;
import java.util.ArrayList;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;

import android.util.Base64;

public class Connections {
	
	//public static String URI = "http://192.168.1.2:8084/Accessible_Worlds_Tomcat/";
	public static String URI = "http://titan.cmpe.boun.edu.tr:8084/Accessible_Worlds_Tomcat/";
	public static String serviceStatus = "serviceStatus.jsp";
	public static String signUp = "signUp.jsp";
	public static String login = "login.jsp";
	public static String search = "search.jsp";
	public static String getViolationTypes = "getViolationTypes.jsp";
	public static String checkEmail = "checkEmail.jsp";
	public static String addressValidation = "addressValidation.jsp";
	public static String forgottenPassword = "forgottenPassword.jsp";
	public static String updatePersonalInformation = "updatePersonalInformation.jsp";
	public static String createReport = "createReport.jsp";
	
	public static String uploadImage = "uploadImage.jsp";
	public static String getImage = "getImage.jsp";
	public static String getImageList = "getImageList.jsp";
	
	public static String uploadVideo = "uploadVideo.jsp";	
	public static String getVideo = "getVideo.jsp";
	public static String getVideoList = "getVideoList.jsp";
	
	public static String addComment = "addComment.jsp";
	public static String getComments = "getComments.jsp";
	public static String addCommentRate = "addCommentRate.jsp";
	public static String getCommentRate = "getCommentRate.jsp";
	
	public static String addReportRate = "addReportRate.jsp";
	public static String getReportRate = "getReportRate.jsp";
	
	public static String sendMessageToAdmin = "sendMessageToAdmin.jsp";
	public static String updateReport = "updateReport.jsp";
	public static String updateComment = "updateComment.jsp";
	
	public static String getOldReports = "getOldReports.jsp";
	
	
	
	public static HttpParams params;
	public static HttpClient client;
	
	public static void initializeVariables() {
		Connections.params = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(Connections.params, 10000);
		HttpConnectionParams.setSoTimeout(Connections.params, 10000);
		HttpProtocolParams.setUseExpectContinue(Connections.params, true);
		Connections.client = new DefaultHttpClient(Connections.params);
	}
	
	public static boolean serviceStatus() {
		try {
			StringBuilder uri = new StringBuilder(URI);
			uri.append(serviceStatus);
			uri.append("?accessCode=");
			uri.append(URLEncoder.encode(encryptString(SharedVariables.serviceSecretKey, URLEncoder.encode(SharedVariables.accessCode,"UTF-8")),"UTF-8"));
			
			HttpPost post = new HttpPost(uri.toString());
			HttpResponse response = client.execute(post);
			
			BufferedReader reader=new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
			StringBuilder stringBuilder = new StringBuilder("");
			String data = "";
			while((data=reader.readLine()) != null) {
				stringBuilder.append(data);
			}
			
			data = stringBuilder.toString();
			data = decryptString(SharedVariables.serviceSecretKey, data);
			
		    String [] takenData = givenData(data);
			
		    for(int i=0;i<takenData.length;i++) {
		    	takenData[i] = URLDecoder.decode(takenData[i], "UTF-8");
		    }

			if("OK".equalsIgnoreCase(takenData[0])) {
				SharedVariables.secretKey = takenData[1];
				return true;
			}
			else {
				SharedVariables.secretKey = takenData[1];
				return false;
			}
		}
		catch (Exception ex) {
			return false;
		}
	}

	public static String [] connection (String url, String [] parameters , String [] paramaterValues) throws Exception {
		
		StringBuilder uri = new StringBuilder(url);
		
		for(int i=0;i<parameters.length;i++) {
			if(i==0) {
				uri.append("?");
			}
			uri.append(parameters[i]);
			uri.append("=");
			uri.append(URLEncoder.encode(encryptString(SharedVariables.secretKey, URLEncoder.encode(paramaterValues[i],"UTF-8")),"UTF-8"));
			if(i!=parameters.length-1) {
				uri.append("&");
			}
		}
		
		HttpPost post = new HttpPost(uri.toString());
		HttpResponse response = client.execute(post);
		
		BufferedReader reader=new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
		StringBuilder stringBuilder = new StringBuilder("");
		String data = "";
		while((data=reader.readLine()) != null) {
			stringBuilder.append(data);
		}
		
		data = stringBuilder.toString();
		data = decryptString(SharedVariables.secretKey, data);
		
		String [] takenData = givenData(data);
		
	    for(int i=0;i<takenData.length;i++) {
	    	takenData[i] = URLDecoder.decode(takenData[i], "UTF-8");
	    }
	    
	    return takenData;
	}
	
	public static String [] connectionWithServiceSecretKey (String url, String [] parameters , String [] paramaterValues) throws Exception {
		
		StringBuilder uri = new StringBuilder(url);
		
		for(int i=0;i<parameters.length;i++) {
			if(i==0) {
				uri.append("?");
			}
			uri.append(parameters[i]);
			uri.append("=");
			uri.append(URLEncoder.encode(encryptString(SharedVariables.serviceSecretKey, URLEncoder.encode(paramaterValues[i],"UTF-8")),"UTF-8"));
			if(i!=parameters.length-1) {
				uri.append("&");
			}
		}
		
		HttpPost post = new HttpPost(uri.toString());
		HttpResponse response = client.execute(post);
		
		BufferedReader reader=new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
		StringBuilder stringBuilder = new StringBuilder("");
		String data = "";
		while((data=reader.readLine()) != null) {
			stringBuilder.append(data);
		}
		
		data = stringBuilder.toString();
		data = decryptString(SharedVariables.serviceSecretKey, data);
		
		String [] takenData = givenData(data);
		
	    for(int i=0;i<takenData.length;i++) {
	    	takenData[i] = URLDecoder.decode(takenData[i], "UTF-8");
	    }
	    
	    return takenData;
	}
	
	public static String [] uploadMedia (String url, String [] parameters , String [] paramaterValues , File file) throws Exception {
		
		FileInputStream fileInputStream = new FileInputStream(file);
		
		URL trueURL = new URL(url);
		HttpURLConnection connection = (HttpURLConnection) trueURL.openConnection();
		connection.setDoInput(true);
        connection.setDoOutput(true);
        HttpURLConnection.setFollowRedirects(true);
        BufferedOutputStream output = new BufferedOutputStream(connection.getOutputStream());
        
        String urlParameters = "";
        for(int i=0;i<parameters.length;i++) {
        	if(i==0) {
        		urlParameters = urlParameters + "?";
			}
        	urlParameters = urlParameters + parameters[i];
        	urlParameters = urlParameters + "=";
        	urlParameters = urlParameters + URLEncoder.encode(encryptString(SharedVariables.serviceSecretKey, URLEncoder.encode(paramaterValues[i],"UTF-8")),"UTF-8");
			if(i!=parameters.length-1) {
				urlParameters = urlParameters + "&";
			}
		}
        
        urlParameters = urlParameters + "&Data=";
        output.write(urlParameters.getBytes());
        
        int c;
        while((c=fileInputStream.read()) != -1) {
            output.write(c);
        }
        output.flush();
        output.close();
        fileInputStream.close();
		
		BufferedReader reader=new BufferedReader(new InputStreamReader(connection.getInputStream()));
		StringBuilder stringBuilder = new StringBuilder("");
		String data = "";
		while((data=reader.readLine()) != null) {
			stringBuilder.append(data);
		}
		
		data = stringBuilder.toString();
		data = decryptString(SharedVariables.serviceSecretKey, data);
		
		String [] takenData = givenData(data);
		
	    for(int i=0;i<takenData.length;i++) {
	    	takenData[i] = URLDecoder.decode(takenData[i], "UTF-8");
	    }
	    
	    return takenData;
	}
	
	public static String getImage (String imageID) throws Exception {
		
		File imageFile = new File(SharedVariables.folderName+File.separator+imageID+".jpg");
		
		if(imageFile.exists()) {
			return "OK";
		}
		else {
			StringBuilder uri = new StringBuilder(Connections.URI);
			uri.append(Connections.getImage);
			uri.append("?");
			uri.append("accessCode");
			uri.append("=");
			uri.append(URLEncoder.encode(encryptString(SharedVariables.serviceSecretKey, URLEncoder.encode(SharedVariables.accessCode,"UTF-8")),"UTF-8"));
			uri.append("&");
			uri.append("imageID");
			uri.append("=");
			uri.append(URLEncoder.encode(encryptString(SharedVariables.serviceSecretKey, URLEncoder.encode(imageID,"UTF-8")),"UTF-8"));
			
			HttpPost post = new HttpPost(uri.toString());
			HttpResponse response = client.execute(post);
			
			InputStream stream = response.getEntity().getContent();
			int downloadingMediaLength = (int) response.getEntity().getContentLength();
			
			byte dataBytes[] = new byte[downloadingMediaLength];
		    int byteRead = 0;
		    int totalBytesRead = 0;
		    while (totalBytesRead < downloadingMediaLength) {
		        byteRead = stream.read(dataBytes, totalBytesRead, downloadingMediaLength);
		        totalBytesRead += byteRead;
		    }
			
			FileOutputStream out = new FileOutputStream(imageFile);
			out.write(dataBytes, 0, downloadingMediaLength);
			out.flush();
			out.close();
			
			return "OK";
		}
	}
	
	public static String getVideo (String videoID) throws Exception {
		
		File videoFile = new File(SharedVariables.folderName+File.separator+videoID+".3gp");
		
		if(videoFile.exists()) {
			return "OK";
		}
		else {
			StringBuilder uri = new StringBuilder(Connections.URI);
			uri.append(Connections.getVideo);
			uri.append("?");
			uri.append("accessCode");
			uri.append("=");
			uri.append(URLEncoder.encode(encryptString(SharedVariables.serviceSecretKey, URLEncoder.encode(SharedVariables.accessCode,"UTF-8")),"UTF-8"));
			uri.append("&");
			uri.append("videoID");
			uri.append("=");
			uri.append(URLEncoder.encode(encryptString(SharedVariables.serviceSecretKey, URLEncoder.encode(videoID,"UTF-8")),"UTF-8"));
			
			HttpPost post = new HttpPost(uri.toString());
			HttpResponse response = client.execute(post);
			
			InputStream stream = response.getEntity().getContent();
			int downloadingMediaLength = (int) response.getEntity().getContentLength();
			
			byte dataBytes[] = new byte[downloadingMediaLength];
		    int byteRead = 0;
		    int totalBytesRead = 0;
		    while (totalBytesRead < downloadingMediaLength) {
		        byteRead = stream.read(dataBytes, totalBytesRead, downloadingMediaLength);
		        totalBytesRead += byteRead;
		    }
			
			FileOutputStream out = new FileOutputStream(videoFile);
			out.write(dataBytes, 0, downloadingMediaLength);
			out.flush();
			out.close();
			
			return "OK";
		}
	}
	
	public static String encryptString(String key , String data) {
        try {
            KeySpec keySpec = new DESKeySpec(Left(key.getBytes("UTF-8"),8));
            SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(keySpec);
            IvParameterSpec iv = new IvParameterSpec(decodeHex("1234567890ABCDEF".toCharArray()));
            
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey,iv);
            
            return Base64.encodeToString(cipher.doFinal(data.getBytes("UTF-8")),0);
        }
        catch (Exception e) {
            return "";
        }
    }
    
    public static String decryptString(String key , String data) {
        try {
            KeySpec keySpec = new DESKeySpec(Left(key.getBytes("UTF-8"),8));
            SecretKey secretKey = SecretKeyFactory.getInstance("DES").generateSecret(keySpec);
            IvParameterSpec iv = new IvParameterSpec(decodeHex("1234567890ABCDEF".toCharArray()));
            
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey,iv);
            
            return new String(cipher.doFinal(Base64.decode(data,0)));
        }
        catch (Exception e) {
            return "";
        }
    }
    
    private static byte[] Left(byte[] bytes, int lenght) {
        byte [] tmp = new byte[lenght];
        for(int i=0;i<lenght;i++) {
            if(i<bytes.length) {
                tmp[i] = bytes[i];
            }
            else {
                tmp[i] = ' ';
            }
        }
        return tmp;
    }
    
    private static byte[] decodeHex (char []  data) {
        int lenght = data.length;
        if((lenght & 0x01) != 0) {
                return null;
        }
        byte [] out = new byte[lenght >> 1];
        for (int i=0 , j =0;j < lenght ; i++) {
                int f = Character.digit(data[j], 16) << 4;
                j++;
                f = f | Character.digit(data[j], 16);
                j++;
                out[i] = (byte) (f & 0xFF);
        }
        return out;
    }
    
    private static String [] givenData(String data) {
    	ArrayList<String> tmpList = new ArrayList<String>();
    	String tmpString = "";
    	for(int i=0; i<data.length();i++) {
    		if(data.charAt(i)!=' ') {
    			tmpString = tmpString + data.charAt(i);
    		}
    		else {
    			tmpList.add(tmpString);
    			tmpString="";
    		}
    	}
    	if(!"".equalsIgnoreCase(tmpString)) {
    		tmpList.add(tmpString);
    	}
    	String [] tmpArray = new String[tmpList.size()];
    	for(int i=0;i<tmpList.size();i++) {
    		tmpArray[i] = tmpList.get(i);
    	}
    	return tmpArray;
    }
}
